package com.devops.admin.util;

import com.devops.admin.model.RedisClientOps;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @ClassName PriorityQueue
 * @Description TODO
 * @Author heyabo
 * @Date 2022/9/22 09:03
 * @Version 1.0
 **/
public class DOSPriorityQueue {
    /**
     * 队列存储的数据
     **/
    private final Map<String,Object> map = new HashMap<>();
    /**
     * 数组大小
     **/
    private int size = 10;

    private final static DOSPriorityQueue priorityQueue = new DOSPriorityQueue();

    public static DOSPriorityQueue getInstance(){
        return priorityQueue;
    }

    /**
     * @Author heyabo
     * @Description 初始化队列
     * @Date 10:09 2022/9/21
     * @Param [maxSize]
     * @return
     **/
    private DOSPriorityQueue(){
    }

    /**
     * @Author heyabo
     * @Description 判断队列是否为空
     * @Date 10:08 2022/9/21
     * @Param []
     * @return boolean
     **/
    public boolean isEmpty(){
        return (map.size()==0);
    }

    /**
     * @Author heyabo
     * @Description 判断队列是否已满
     * @Date 10:08 2022/9/21
     * @Param []
     * @return boolean
     **/
    public boolean isFull(){
        return (map.size()==size);
    }

    /**
     * @Author heyabo
     * @Description 队列实际存储数量大小
     * @Date 10:08 2022/9/21
     * @Param []
     * @return int
     **/
    public int size(){
        return map.size();
    }

    /**
     * @Author heyabo
     * @Description 往队列添加数据
     * @Date 10:08 2022/9/21
     * @Param [value]
     * @return void
     **/
    public void insert(String key,Object value){
        synchronized (this) {
            if (isFull()) {
                // 如果队列已满，则清除队列里的不常用的数据或者对队列进行扩容
                remove();
            }
            RedisClientOps clientOps = (RedisClientOps) value;
            if (clientOps.getLevel() == null || clientOps.getLevel() == 0){
                clientOps.setLevel(3);
            }
            //空队列直接添加
            if (map.size() == 0) {
                map.put(key, clientOps);
            } else {
                // 如果队列不为空则循环为队列里的链接减一操作
                exchangeLevel();
                map.put(key,clientOps);
            }
            size++;
        }
    }

    /**
     * @Author heyabo
     * @Description 删除标志统一减一
     * @Date 11:10 2022/9/21
     * @Param []
     * @return void
     **/
    private void exchangeLevel() {
        for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Object> item = it.next();
            RedisClientOps client = (RedisClientOps) item.getValue();
            if (client.getLevel() == 0) {
                // 关闭redis连接客户端
                client.getClient().shutdown();
                // 关闭redis连接
                client.getConnect().close();
                it.remove();
                size--;
            }else {
                client.setLevel((client.getLevel() - 1));
                map.put(item.getKey(), client);
            }
        }
    }

    /**
     * @Author heyabo
     * @Description 删除数据
     * @Date 09:15 2022/9/22
     * @Param []
     * @return boolean
     **/
    public boolean remove(){
        synchronized (this) {
            boolean bool = false;
            int leval = 0;
            for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry<String, Object> item = it.next();
                RedisClientOps client = (RedisClientOps) item.getValue();

                if ((leval = client.getLevel()) == 0) {
                    // 关闭redis客户端
                    client.getClient().shutdown();
                    // 关闭redis连接
                    client.getConnect().close();
                    bool = true;
                    it.remove();
                    size--;
                }
            }
            if (!bool){
                cleanCode();
            }
            return bool;
        }
    }

    /**
     * @Author heyabo
     * @Description 清理节点
     * @Date 09:32 2022/9/22
     * @Param [leval]
     * @return void
     **/
    private void cleanCode() {
        int level = 2;
        int removeLevel;
        String key = "";
        do{
            removeLevel = level;
            for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
                RedisClientOps client = (RedisClientOps) stringObjectEntry.getValue();
                if (client.getLevel() < 2){
                    key = stringObjectEntry.getKey();
                    level = client.getLevel();
                }
            }
            level++;
        }while (key != null && !key.equals(""));

        // 删除同级别的节点
        for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Object> item = it.next();
            RedisClientOps client = (RedisClientOps) item.getValue();
            if (removeLevel == client.getLevel()) {
                // 关闭redis客户端
                client.getClient().shutdown();
                // 关闭redis连接
                client.getConnect().close();
                it.remove();
                size--;
            }
        }
    }

    /**
     * @Author heyabo
     * @Description 获取redisClient
     * @Date 11:27 2022/9/21
     * @Param [key]
     * @return org.javaboy.springredisdemo.RedisClient
     **/
    public RedisClientOps getClient(String key){
        synchronized (this){
            RedisClientOps client = (RedisClientOps) map.get(key);
            if (client != null){
                client.setLevel(client.getLevel() +1);
                map.put(key,client);
            }

            return client;
        }
    }

    //打印 队列
    public void display(){
        if (!isEmpty()) {
            map.forEach((key, value) -> System.out.println(value));
        }
        System.out.println(" ");
    }
}
